#ifndef AUDIO_H
#define AUDIO_H

#include <stdlib.h>
#include <stdio.h>
#include <vector>
#include <cstring>
#include <string>

#include <AL/al.h>
#include <AL/alc.h>
#include <AL/alut.h>

/*
 * Enumerations
 */

typedef enum{
    AUDIO_MENU_OVER,
    AUDIO_MENU_CLICK,
    AUDIO_MENU_LEVEL,
    AUDIO_COLLISION,
    AUDIO_FALLOUT,
    AUDIO_ENDZONE,
    AUDIO_COLLECT1,
	AUDIO_COLLECT2,
	AUDIO_COLLECT3,
	AUDIO_LIFEUP,
	AUDIO_POWERDOWN,
	AUDIO_POWERDOWN_OFF,
    AUDIO_TELEPORT_IN,
    AUDIO_TELEPORT_OUT,
	AUDIO_GROW,
	AUDIO_SHRINK,
	AUDIO_EXTRATIME
} SourceIndex;

typedef enum{
    AUDIO_SFX,
    AUDIO_BGM
} SourceType;

typedef enum{
    relative,
    absolute
} SourcePosition;

/*
 * Structures
 */
typedef struct {
    ALfloat x, y, z;
} ALvector;

typedef struct {
    ALvector at;
    ALvector up;
} ALorientation;

#define NUM_BGM_FILES 4

class AudioInterface
{
    public:
        AudioInterface(void);
       ~AudioInterface(void);
        AudioInterface(const AudioInterface&);
        AudioInterface& operator=(AudioInterface&);
        
        // abstracted methods
        void loadRandomBGM();
        void playBGM();
        void stopBGM();
        void playMenuBGM();
        void pauseBGM();
        void stopMenuBGM();
        bool isPlayingMenuBGM() { return playingMenuBGM; }
        
        // listener methods
        void setListenerPosition(Ogre::Vector3);
        void setListenerVelocity(Ogre::Vector3);
        void setListenerOrientation(Ogre::Vector3 at, Ogre::Vector3 up);
        
        // source methods
        void setDefaultSourceParams(ALuint);
        int createSource(SourceIndex, SourcePosition, SourceType, std::string);
        int createSource(SourceIndex, SourcePosition, SourceType, std::string, Ogre::Vector3);
        void playSource(SourceIndex);
        void pauseSource(SourceIndex);
        void stopSource(SourceIndex);
        void setSourcePitch(SourceIndex, float);
        void setSourceGain(SourceIndex, float);
        void setSourcePosition(SourceIndex, Ogre::Vector3);
        void setSourceVelocity(SourceIndex, Ogre::Vector3);
        void setSourceLoop(SourceIndex, bool);
        void setVolumeBGM(float volume);
        void setVolumeSFX(float volume);

    private:

        ALboolean init();
        void initListenerValues();
        ALuint getBuffer(std::string);
        const char *getALErrorString(ALenum err);
        const char *getALCErrorString(ALenum err);
        std::string bgmFiles[NUM_BGM_FILES];
        bool playingMenuBGM;
            
        ALCdevice *device;
        ALCcontext *context;
           
        std::vector<ALuint> buffers;
        std::vector<ALuint> sources;
        std::vector<ALuint>::iterator it;
        std::vector<std::string> loadedFiles;
        ALuint bgmSource, bgmBuffer;
        ALuint bgmMenuSource, bgmMenuBuffer;
        
        ALvector listenerPos;
        ALvector listenerVel;
        ALorientation listenerOri;
};

#endif
